import { getFileUploadToken } from '@/api/wx/wx';
import CosAuth from '@/lib/cos-auth/index';
import type { NSFileUpload } from '@/models/file-upload';
import Taro from '@tarojs/taro';
import { useEffect, useState } from 'react';

export default function useCosFile() {
  const [uploadStatus, setUploadStatus] = useState<0 | 1>(1);

  const [cosInitData, setCosInitData] = useState({} as NSFileUpload.IData);
  const [imgUrl, setImgUrl] = useState('' as string | string[]);
  /**
   *
   * @param tp 选择类型
   * @param ct 可以上传个数
   * @param uploadBeforeHooks  上传前钩子 file：临时文件
   * @param uploadFaildHooks  上传失败钩子 file：临时文件
   * @returns
   */
  async function uploadFileFun(
    tp?: (keyof Taro.chooseImage.sourceType)[],
    ct?: number,
    uploadBeforeHooks?: (file: any) => boolean,
    uploadFaildHooks?: (file: any) => void,
  ) {
    const count = ct ? ct : 1;
    setUploadStatus(0);
    let sourceType: (keyof Taro.chooseImage.sourceType)[] = ['album', 'camera'];
    if (tp) {
      sourceType = tp;
    }

    const uploadBefore = uploadBeforeHooks || (() => true);
    const uploadFaild = uploadFaildHooks || (() => {});
    let tempFilePath = ''; //临时文件
    return await new Promise((resolve, reject) => {
      const config = {
        bucket: cosInitData.Bucket,
        region: cosInitData.Region,
      };
      // 图片存储前缀
      const prefix = 'https://' + config.bucket + '.cos.' + config.region + '.myqcloud.com/';
      // const interfacePrefix = cosInitData.Cdn + '/';
      // 对更多字符编码的 url encode 格式
      const camSafeUrlEncode = function (str: string) {
        return encodeURIComponent(str)
          .replace(/!/g, '%21')
          .replace(/'/g, '%27')
          .replace(/\(/g, '%28')
          .replace(/\)/g, '%29')
          .replace(/\*/g, '%2A');
      };

      // 获取临时密钥
      const getCredentials = function (callback: Function) {
        if (cosInitData && Date.now() / 1000 + 30 < cosInitData.ExpiredTime) {
          getFileUploadToken()
            .then((res: NSFileUpload.IResult) => {
              if (res.code === 200) {
                callback(res.data.Credentials);
              }
            })
            .catch(() => {
              uploadFaild(tempFilePath);
            });
          return;
        }
        callback(cosInitData && cosInitData.Credentials);
      };

      // 计算签名
      const getAuthorization = function (
        options: { Method: string; Pathname: string },
        callback: Function,
      ) {
        getCredentials(function (credentials: NSFileUpload.ICredentials) {
          callback({
            XCosSecurityToken: credentials.Token,
            Authorization: CosAuth({
              SecretId: credentials.TmpSecretId,
              SecretKey: credentials.TmpSecretKey,
              Method: options.Method,
              Pathname: options.Pathname,
            }),
          });
        });
      };

      // 上传文件
      const uploadFile = async function (filePath: string) {
        return await new Promise((resolve1, reject1) => {
          const Key = filePath.substr(filePath.lastIndexOf('/') + 1); // 这里指定上传的文件名
          getAuthorization(
            { Method: 'POST', Pathname: '/' },
            function (AuthData: { XCosSecurityToken: string; Authorization: string }) {
              const uploadTask = Taro.uploadFile({
                url: prefix,
                name: 'file',
                filePath: filePath,
                formData: {
                  key: Key,
                  success_action_status: 200,
                  Signature: AuthData.Authorization,
                  'x-cos-security-token': AuthData.XCosSecurityToken,
                  'Content-Type': '',
                },
                success: function (res: any) {
                  const url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
                  // const interfaceUrl = interfacePrefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
                  // const url = interfaceUrl;

                  if (res.statusCode === 200) {
                    resolve1(url);
                  } else {
                    Taro.showModal({
                      title: '上传失败',
                      content: JSON.stringify(res),
                      showCancel: false,
                    });
                    uploadFaild(filePath);
                  }
                },
                fail: function (res: any) {
                  Taro.showModal({
                    title: '上传失败',
                    content: JSON.stringify(res),
                    showCancel: false,
                  });
                  reject1();
                  reject();
                  uploadFaild(filePath);
                },
                complete() {
                  setTimeout(() => {
                    setUploadStatus(1);
                  }, 1000);
                },
              });
              uploadTask.progress(function () {});
            },
          );
        });
      };

      // 选择文件
      Taro.chooseImage({
        count, // 默认9
        sizeType: ['original'], // 指定是原图还是压缩图，这里默认用原图
        sourceType, // 指定是相册还是相机
        success: async function (res: any) {
          const isCanUpload = await uploadBefore(res);
          tempFilePath = res.tempFiles;
          if (!isCanUpload) {
            uploadFaild(tempFilePath);
            return;
          }
          setUploadStatus(0);
          if (res.tempFiles.length === 1) {
            const tempUrl = (await uploadFile(res.tempFiles[0].path)) as string;
            setImgUrl(tempUrl);
            resolve(tempUrl);
          } else {
            const tempUrlArr = [] as string[];
            res.tempFiles.map(async (item: { path: string }) => {
              const tempUrl = (await uploadFile(item.path)) as string;
              tempUrlArr.push(tempUrl);
              Promise.all(tempUrlArr).then(function (results) {
                if (res.tempFiles.length === results.length) {
                  setImgUrl(results);
                  resolve(results);
                }
              });
            });
          }
        },
        fail(err) {
          uploadFaild(tempFilePath);
          if (err.errMsg !== 'chooseImage:fail cancel') {
            Taro.showModal({
              title: '上传图片失败，请重新上传！',
              showCancel: false,
            });
          }
        },
      });
    });
  }
  useEffect(() => {
    getFileUploadToken().then((res: NSFileUpload.IResult) => {
      if (res.code === 200) {
        setCosInitData(res.data);
      }
    });
  }, []);

  return { uploadFileFun, imgUrl, uploadStatus };
}
